package Operators;


import java.util.ArrayList;


import States.WaterCupState;
import Templates.Operator;


public class WaterCupOperators {
	
	private static ArrayList<Operator<WaterCupState>> waterCupOperators=new ArrayList<Operator<WaterCupState>>();
	
	public static ArrayList<Operator<WaterCupState>> returnOperators()
	{
		waterCupOperators.add(new Fill1());
		waterCupOperators.add(new Fill2());
		waterCupOperators.add(new Empty1());
		waterCupOperators.add(new Empty2());
		waterCupOperators.add(new Empty_1to2());
		waterCupOperators.add(new Empty_2to1());
		return waterCupOperators;
	}
	

	public static class Fill1 implements Operator<WaterCupState>{

		public int getOperatorNumber()
		{
			return 1;
		}
		public WaterCupState execute(WaterCupState s)
		{
				return new WaterCupState(3,s.getCapacity2());

		}
		public boolean available(WaterCupState s)
		{
			if (s.getCapacity1()<3)
			return true;
			else return false;
		}
		public String toString()
		{
			return "Filling first cup";
		}

	}
	
	public static class Fill2 implements Operator<WaterCupState>{
		public int getOperatorNumber()
		{
			return 2;
		}

		public WaterCupState execute(WaterCupState s)
		{
				return new WaterCupState(s.getCapacity1(),4);

		}
		
		public boolean available(WaterCupState s)
		{
			if (s.getCapacity2()<4)
			return true;
			else return false;
		}
		public String toString()
		{
			return "Filling second cup";
		}

	}
	
	public static class Empty1 implements Operator<WaterCupState>{

		public int getOperatorNumber()
		{
			return 3;
		}
		public WaterCupState execute(WaterCupState s)
		{

				return new WaterCupState(0,s.getCapacity2());

		}
		public boolean available(WaterCupState s)
		{
			if (s.getCapacity1()>0)
			return true;
			else return false;
		}
		public String toString()
		{
			return "Empting first cup";
		}

	}
	
	public static class Empty2 implements Operator<WaterCupState>{

		public int getOperatorNumber()
		{
			return 4;
		}
		public WaterCupState execute(WaterCupState s)
		{

				return new WaterCupState(s.getCapacity1(),0);

		}
		public boolean available(WaterCupState s)
		{
			if (s.getCapacity2()>0)
			return true;
			else return false;
		}
		public String toString()
		{
			return "Empting second cup";
		}

	}
	
	public static class Empty_1to2 implements Operator<WaterCupState>{

		public int getOperatorNumber()
		{
			return 5;
		}
		public WaterCupState execute(WaterCupState s)
		{

			int aux1=min(4,s.getCapacity1()+s.getCapacity2());
			int aux2=Math.abs(3-(s.getCapacity1()+s.getCapacity2()));
			WaterCupState s2=new WaterCupState(aux2,aux1);
			return s2;
		}
		public boolean available(WaterCupState s)
		{
			if (s.getCapacity2()<4 && s.getCapacity1()>0)
			return true;
			else return false;
		}
		public int min(int a,int b)
		{		
			if (a<b) return a; else return b;
		}
		public String toString()
		{
			return "Filling second using first cup";
		}

		
	}
	
	public static class Empty_2to1 implements Operator<WaterCupState>{
		
		
		public int getOperatorNumber()
		{
			return 6;
		}
		public WaterCupState execute(WaterCupState s)
		{
			
			int aux1=min(3,s.getCapacity1()+s.getCapacity2());
			int aux2=0;
			if (s.getCapacity2()<3-s.getCapacity1()) aux2=0;
			else aux2=Math.abs(3-(s.getCapacity1()+s.getCapacity2()));
			WaterCupState s2=new WaterCupState(aux1,aux2);
			return s2;

		}
		public boolean available(WaterCupState s)
		{
			if (s.getCapacity2()>0 && s.getCapacity1()<3)
			return true;
			else return false;
		}
		public int min(int a,int b)
		{		
			if (a<b) return a; else return b;
		}
		public String toString()
		{
			return "Filling first using second cup";
		}

	}
	public static class InitialState implements Operator<WaterCupState>
	{
		public String toString(){
	
		return "Initial State";
	}
		
		public int getOperatorNumber()
		{
			return 0;
		}
		
	
	public WaterCupState execute(WaterCupState s)
	{
		return null;
	}
	
	public boolean available(WaterCupState s)
	{
		return false;
		
	}
	}



}
